package com.karolak.sm.station;

import java.util.ArrayList;
import java.util.List;

import com.karolak.sm.StateMachine;
import com.karolak.sm.StateMachineImpl;
import com.karolak.sm.exception.TransitionException;
import com.karolak.sm.state.State;
import com.karolak.sm.state.Transition;
import com.karolak.sm.station.StationConstants.PartStateId;
import com.karolak.sm.station.StationConstants.ProductEvent;
import com.karolak.sm.station.StationConstants.ProductStateId;
import com.karolak.sm.station.StationConstants.StationEvent;
import com.karolak.sm.station.StationConstants.StationStateId;
import com.karolak.sm.station.state.StationState;
import com.karolak.sm.station.state.StationStateBase;

public class Station extends StateMachineImpl implements StateMachine, StationState {

	public Station() {

		List<State> states = new ArrayList<State>();
		List<Transition> transitions = new ArrayList<Transition>();

		// === station events and transitions === //
		states.add(new StationStateBase(this, StationStateId.STOPPED));
		states.add(new StationStateBase(this, StationStateId.IDLE));
		states.add(new StationStateBase(this, StationStateId.LOCKED));

		transitions.add(new Transition(StationEvent.START, StationStateId.STOPPED, StationStateId.IDLE));
		transitions.add(new Transition(StationEvent.LOCK, StationStateId.IDLE, StationStateId.LOCKED));
		transitions.add(new Transition(StationEvent.UNLOCK, StationStateId.LOCKED, StationStateId.IDLE));
		transitions.add(new Transition(StationEvent.STOP, StationStateId.IDLE, StationStateId.STOPPED));

		// === product events and transitions === //
		states.add(new StationStateBase(this, ProductStateId.PROCESSING_PRODUCT));
		transitions.add(new Transition(ProductEvent.START_PRODUCT, StationStateId.IDLE, ProductStateId.PROCESSING_PRODUCT));
		transitions.add(new Transition(ProductEvent.FINISH_PRODUCT, ProductStateId.PROCESSING_PRODUCT, StationStateId.IDLE));

		
		// === product events and transitions === //
		states.add(new StationStateBase(this, PartStateId.PROCESSING_PART));
		transitions.add(new Transition(ProductEvent.START_PRODUCT, StationStateId.IDLE, ProductStateId.PROCESSING_PRODUCT));
		transitions.add(new Transition(ProductEvent.FINISH_PRODUCT, ProductStateId.PROCESSING_PRODUCT, StationStateId.IDLE));
		
		
		registerStates(states);
		registerTransitions(transitions);

		setState(getConfig().getState(StationStateId.STOPPED));

	}

	// === station operations === //
	public void start() {
		try {
			getState().start();
		} catch (TransitionException e) {
			handleException(e);
		}
	}

	public void lock() {
		try {
			getState().lock();
		} catch (TransitionException e) {
			handleException(e);
		}
	}

	public void unlock() {
		try {
			getState().unlock();
		} catch (TransitionException e) {
			handleException(e);
		}
	}

	public void stop() {
		try {
			getState().stop();
		} catch (TransitionException e) {
			handleException(e);
		}
	}

	// === product operations === //
	public void startProduct() {
		try {
			getState().startProduct();
		} catch (TransitionException e) {
			handleException(e);
		}
	}

	public void finishProduct() {
		try {
			getState().finishProduct();
		} catch (TransitionException e) {
			handleException(e);
		}
	}

	@Override
	public StationState getState() {
		return (StationState) super.getState();
	}

	// === interface === //

	/*
	 * public void update(StationEvent stationEvent) {
	 * 
	 * }
	 * 
	 * public void start() { getState().start(); }
	 * 
	 * public void stop() { getState().stop();
	 * 
	 * }
	 * 
	 * public void lock() { getState().lock(); }
	 * 
	 * public void unlock() { getState().unlock();
	 * 
	 * }
	 * 
	 * // === get/set === // protected StationState getState() { return state; }
	 * 
	 * protected void setState(StationState state) { this.state = state; }
	 * 
	 * protected static StationState getState(StateId stateId) { return
	 * getStates().get(stateId); }
	 * 
	 * protected static Map<StateId, StationState> getStates() { return states;
	 * }
	 * 
	 * protected StateConfig getConfig() { return config; }
	 */
}
